import * as d3 from "d3";

export class ComboChart {
    constructor(container) {
        this.container = container;
        this.margin = { top: 60, right: 120, bottom: 60, left: 70 };
        this.width = 1000;  
        this.height = 900; 
        
        this.handlers = {};

        // 创建SVG
        this.svg = d3.select(container)
            .append('svg')
            .attr('width', this.width + this.margin.left + this.margin.right)
            .attr('height', this.height + this.margin.top + this.margin.bottom)
            .append('g')
            .attr('transform', `translate(${this.margin.left},${this.margin.top})`);

        // 创建左右Y轴
        this.yAxisLeft = d3.scaleLinear()
            .range([this.height, 0]);
        
        this.yAxisRight = d3.scaleLinear()
            .domain([0, 5])
            .range([this.height, 0]);
            
        // 添加标题
        this.svg.append('text')
            .attr('class', 'chart-title')
            .attr('x', this.width / 2)
            .attr('y', -30)
            .attr('text-anchor', 'middle')
            .style('font-size', '20px')
            .style('font-weight', 'bold')
            .text('各专业AI使用场景分布与满意度');

        // 添加鼠标移出事件
        this.svg.on('mouseleave', () => {
            // 恢复所有柱子和点的样式
            this.svg.selectAll('rect')
                .transition()
                .duration(200)
                .style('stroke', 'white')
                .style('stroke-width', 2)
                .style('filter', 'none')
                .attr('transform', 'scale(1)');
            
            // 触发其他图表恢复
            this.handlers['majorOut']?.();
        });
    }

    // 添加事件处理方法
    on(eventName, handler) {
        this.handlers[eventName] = handler;
    }

    update(data) {
        const scenarios = ['学术研究', '课程学习', '创意启发', '生活日常', '职业发展'];
        const majors = data.map(d => d.major);

        // 清除之前的内容（保留标题）
        this.svg.selectAll('g').remove();

        // 设置Y轴刻度范围和间隔
        this.yAxisLeft
            .domain([0, 80])  
            .ticks(8);  

        // 设置比例尺
        const x = d3.scaleBand()
            .domain(majors)
            .range([0, this.width])
            .padding(0.5);  

        this.yAxisLeft.domain([0, d3.max(data, d => d.total)]);

        const color = d3.scaleOrdinal()
            .domain(scenarios)
            .range([
                '#99B4D1',  
                '#FFEB99',  
                '#E6B3CC', 
                '#B3D9B3',  
                '#FFB366'   
            ]);

        // 准备堆叠数据
        const stack = d3.stack()
            .keys(scenarios)
            .value((d, key) => d.scenarios[key] || 0)
            .order(d3.stackOrderNone)  
            .offset(d3.stackOffsetNone);  

        const stackedData = stack(data);

        const yMax = d3.max(stackedData, layer => d3.max(layer, d => d[1]));
        const yAxisMax = Math.ceil(yMax / 10) * 10;  
        
        this.yAxisLeft
            .domain([0, yAxisMax])  
            .ticks(8);  

        // 添加tooltip div
        const tooltip = d3.select(this.container)
            .append('div')
            .attr('class', 'tooltip')
            .style('opacity', 0)
            .style('position', 'absolute')
            .style('background-color', 'white')
            .style('padding', '10px')
            .style('border-radius', '5px')
            .style('box-shadow', '0 2px 4px rgba(0,0,0,0.1)');

        // 绘制堆叠柱状图
        const barGroups = this.svg.append('g')
            .selectAll('.bar-group')
            .data(stackedData)
            .join('g')
            .attr('class', 'bar-group')
            .attr('fill', d => color(d.key));

        // 添加渐变效果
        const defs = this.svg.append('defs');
        
        // 为每个场景创建渐变
        const gradients = {
            '学术研究': ['#99B4D1', '#7393B3'],
            '课程学习': ['#FFEB99', '#FFD700'],
            '创意启发': ['#E6B3CC', '#D896B0'],
            '生活日常': ['#B3D9B3', '#90C290'],
            '职业发展': ['#FFB366', '#FF9933']
        };

        Object.entries(gradients).forEach(([key, [color1, color2]]) => {
            const gradient = defs.append('linearGradient')
                .attr('id', `gradient-${key}`)
                .attr('gradientTransform', 'rotate(90)');

            gradient.append('stop')
                .attr('offset', '0%')
                .attr('stop-color', color1);

            gradient.append('stop')
                .attr('offset', '100%')
                .attr('stop-color', color2);
        });

        // 柱状图样式
        barGroups.selectAll('rect')
            .data(d => d)
            .join('rect')
            .attr('x', d => x(d.data.major))
            .attr('y', d => this.yAxisLeft(d[1]))
            .attr('height', d => Math.max(0, this.yAxisLeft(d[0]) - this.yAxisLeft(d[1])))
            .attr('width', x.bandwidth())
            .attr('rx', 4)  
            .attr('fill', function(d) {
                const scenarioName = d3.select(this.parentNode).datum().key;
                return `url(#gradient-${scenarioName})`;
            })
            .style('stroke', 'white')
            .style('stroke-width', 1)
            .style('filter', 'drop-shadow(0 2px 2px rgba(0,0,0,0.1))')  
            .on('mouseover', (event, d) => {
                d3.select(event.currentTarget)
                    .style('filter', 'drop-shadow(0 4px 4px rgba(0,0,0,0.2))')
                    .style('cursor', 'pointer')
                    .transition()
                    .duration(300)
                    .attr('transform', 'scale(1.02)');
                    
                tooltip.transition()
                    .duration(200)
                    .style('opacity', 1);
                const currentValue = d[1] - d[0];  
                const majorTotal = d.data.total;   
                
                tooltip.html(`
                    <div style="padding: 8px;">
                        <div style="font-weight: bold; margin-bottom: 5px;">
                            ${d3.select(event.currentTarget.parentNode).datum().key}
                        </div>
                        <div>使用人数: ${currentValue}</div>
                        <div>专业覆盖率: ${((currentValue / d.data.total) * 100).toFixed(1)}%</div>
                        <div>场景占比: ${((currentValue / d.data.totalSelections) * 100).toFixed(1)}%</div>
                        <div class="note" style="font-size: 12px; color: #666;">
                            * 专业覆盖率：选择该场景的人数占专业总人数的比例
                            * 场景占比：该场景在所有场景选择中的占比
                        </div>
                    </div>
                `)
                    .style('left', `${event.offsetX + 10}px`)
                    .style('top', `${event.offsetY + 10}px`);

                this.handlers['majorHover']?.(d.data.major);
            })
            .on('mouseout', (event, d) => {
                d3.select(event.currentTarget)
                    .style('filter', 'drop-shadow(0 2px 2px rgba(0,0,0,0.1))')
                    .transition()
                    .duration(300)
                    .attr('transform', 'scale(1)');
                    
                tooltip.transition()
                    .duration(500)
                    .style('opacity', 0);
                    
                this.handlers['majorOut']?.();
            });

        // 绘制满意度折线
        const line = d3.line()
            .x(d => x(d.major) + x.bandwidth() / 2)
            .y(d => this.yAxisRight(d.satisfaction))
            .curve(d3.curveMonotoneX); 

        // 美化满意度线和点
        this.svg.append('path')
            .datum(data)
            .attr('class', 'satisfaction-line')
            .attr('fill', 'none')
            .attr('stroke', '#336699')
            .attr('stroke-width', 3)
            .attr('stroke-linecap', 'round')
            .attr('filter', 'drop-shadow(0 1px 2px rgba(0,0,0,0.1))')
            .attr('d', line);

        // 满意度点添加动画效果
        this.svg.selectAll('.satisfaction-point')
            .data(data)
            .join('circle')
            .attr('class', 'satisfaction-point')
            .attr('cx', d => x(d.major) + x.bandwidth() / 2)
            .attr('cy', d => this.yAxisRight(d.satisfaction))
            .attr('r', 6)
            .attr('fill', '#4E79A7')
            .attr('stroke', 'white')
            .attr('stroke-width', 2)
            .style('filter', 'drop-shadow(0 2px 2px rgba(0,0,0,0.1))')
            .on('mouseover', (event, d) => {
                d3.select(event.currentTarget)
                    .transition()
                    .duration(300)
                    .attr('r', 8)
                    .style('filter', 'drop-shadow(0 4px 4px rgba(0,0,0,0.2))')
                    .style('cursor', 'pointer');
                    
                tooltip.transition()
                    .duration(200)
                    .style('opacity', 1);
                    
                tooltip.html(`
                    <div style="padding: 8px;">
                        <div style="font-weight: bold; margin-bottom: 5px;">${d.major}</div>
                        <div>满意度: ${d.satisfaction.toFixed(1)}</div>
                    </div>
                `)
                    .style('left', `${event.offsetX + 10}px`)
                    .style('top', `${event.offsetY + 10}px`);

                this.handlers['majorHover']?.(d.major);
            })
            .on('mouseout', (event, d) => {
                d3.select(event.currentTarget)
                    .transition()
                    .duration(300)
                    .attr('r', 6)
                    .style('filter', 'drop-shadow(0 2px 2px rgba(0,0,0,0.1))');
                    
                tooltip.transition()
                    .duration(500)
                    .style('opacity', 0);
                    
                this.handlers['majorOut']?.();
            });

        // 美化tooltip
        tooltip
            .style('background-color', 'rgba(255, 255, 255, 0.95)')
            .style('border-radius', '6px')
            .style('padding', '0')
            .style('box-shadow', '0 4px 6px rgba(0, 0, 0, 0.1)')
            .style('pointer-events', 'none')
            .style('font-size', '14px');

        // 添加坐标轴
        this.svg.append('g')
            .attr('transform', `translate(0,${this.height})`)
            .call(d3.axisBottom(x))
            .selectAll('text')
            .style('text-anchor', 'middle')
            .style('font-size', '14px');

        // 左Y轴
        this.svg.append('g')
            .call(d3.axisLeft(this.yAxisLeft))
            .call(g => g.select('.domain').remove())
            .call(g => g.selectAll('.tick text')
                .style('font-size', '14px'))
            .append('text')
            .attr('fill', '#666')
            .attr('y', -20)
            .attr('x', -10)
            .style('font-size', '14px')
            .text('使用人数');

        // 右Y轴
        this.svg.append('g')
            .attr('transform', `translate(${this.width},0)`)
            .call(d3.axisRight(this.yAxisRight))
            .call(g => g.select('.domain').remove())
            .call(g => g.selectAll('.tick text')
                .style('font-size', '14px'))
            .append('text')
            .attr('fill', '#666')
            .attr('y', -20)
            .attr('x', 10)
            .style('font-size', '14px')
            .text('满意度');

        // 添加图例
        const legend = this.svg.append('g')
            .attr('class', 'legend')
            .attr('transform', `translate(${this.width + 40}, 0)`);

        scenarios.forEach((scenario, i) => {
            const legendItem = legend.append('g')
                .attr('transform', `translate(0, ${i * 25})`);

            legendItem.append('rect')
                .attr('width', 15)
                .attr('height', 15)
                .attr('fill', color(scenario))
                .attr('rx', 2);

            legendItem.append('text')
                .attr('x', 25)
                .attr('y', 12)
                .style('font-size', '14px')
                .text(scenario);
        });
    }
} 